package com.seng.resourcetycoon.gui.controllers;

import com.seng.resourcetycoon.core.entities.RandomEvent;
import com.seng.resourcetycoon.gui.views.LoadBearerItemView;
import com.seng.resourcetycoon.gui.views.TowerGardItemView;
import com.seng.resourcetycoon.manager.EventManager;
import com.seng.resourcetycoon.manager.GameEnvironment;
import com.seng.resourcetycoon.manager.GameStateHandlerManager;
import com.seng.resourcetycoon.services.GamePlayService;
import com.seng.resourcetycoon.services.LoadBearerService;
import com.seng.resourcetycoon.services.TowerManagementService;
import com.seng.resourcetycoon.services.impl.LoadBearerServiceImpl;
import com.seng.resourcetycoon.services.impl.TowerManagementServiceImpl;
import com.seng.resourcetycoon.util.SceneUtil;
import com.seng.resourcetycoon.util.ToastUtil;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * GamePlayController serves as the controller for managing game play logic, UI interactions,
 * and integration with game services. It implements the GamePlayService and Initializable interfaces,
 * coordinating game states, user interface updates, and handling events during gameplay.
 */
public class GamePlayController implements GamePlayService, Initializable {

    @FXML
    HBox cartPane;
    @FXML
    private GridPane gridView;
    @FXML
    private Label userName;
    @FXML
    private Label coins;
    @FXML
    private Label round;
    private GameStateHandlerManager gameStateManager;
    private final AtomicBoolean isSuccess = new AtomicBoolean(false);
    private LoadBearerService cartManagerService;
    private TowerManagementService towerManagementService;
    private static final int GRID_COLUMNS = 4; // Replace 4 with the desired number of columns

    /**
     * Initializes the controller, setting up services, UI components, and starting the game state.
     *
     * @param url            The location used to resolve relative paths for the root object.
     * @param resourceBundle The resources used to localize the root object.
     */
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        initializeServices();
        setupWindowCloseListener();
        initializeUIComponents();
        gameStateManager.begin();
    }

    private void initializeServices() {
        cartManagerService = new LoadBearerServiceImpl();
        towerManagementService = new TowerManagementServiceImpl();
        gameStateManager = new GameStateHandlerManager(cartManagerService, towerManagementService, EventManager.getInstance());
        gameStateManager.initialize(this);
    }

    private void initializeUIComponents() {
        initializeCartItems();
        initializeTowersView();
        initializeUserInfo();
    }

    private void initializeCartItems() {
        for (LoadBearerItemView loadBearerItemView : cartManagerService.getCartItemViews()) {
            cartPane.getChildren().add(loadBearerItemView.getContent());
        }
    }

    private void initializeTowersView() {
        refreshTowerView();
    }

    private void initializeUserInfo() {
        GameEnvironment gameEnv = GameEnvironment.getInstance();
        userName.setText("Name：" + gameEnv.getUserName());
        coins.setText("Coins：" + gameEnv.getCoin().toPlainString());
        round.setText("Game round：" + gameEnv.getGameRound() + "/" + gameEnv.getMaxGameRound());
    }

    private void setupWindowCloseListener() {
        Platform.runLater(() -> {
            Stage stage = (Stage) cartPane.getScene().getWindow();
            stage.setOnCloseRequest(windowEvent -> {
                dispose();
            });
        });
    }

    @Override
    public void onRandomEvent(RandomEvent event) {
        // Depending on the event type, update UI accordingly
        switch (event.getType()) {
            case TOWER_BOOST:
                break;
            case TOWER_BREAKDOWN:
                towerBreakdownNotification();
                break;
            case RESOURCE_SPAWN:
                cartResourceIncreaseNotification();
                break;
            // Handle other event types...
            default:
                System.out.println("Unrecognized event type: " + event.getType());
        }
    }

    public void towerBreakdownNotification() {
        if(towerManagementService.updateSelectedTowerStateToDamaged()){
            Platform.runLater(() -> {
                ToastUtil.showAlert("Alert! A tower now break down. Tap to replenish!", "" );
            });
        }
    }

    private void cartResourceIncreaseNotification(){
        Platform.runLater(() -> {
            ToastUtil.showAlert("Alert! A cart now needs 30 more resources. Tap to replenish!", "", () -> cartManagerService.randomlyIncreaseResource());
        });
    }

    private void refreshTowerView() {
        List<TowerGardItemView> activeTowersSnapshot = new ArrayList<>(towerManagementService.getAndRefreshTowerCardItemView()); // 复制列表

        for (int i = 0; i < activeTowersSnapshot.size(); i++) {
            TowerGardItemView towerGardItemView = activeTowersSnapshot.get(i);
            // 4. Determine the row and column indices for the TowerView
            int row = i / GRID_COLUMNS; // Assuming a fixed number of columns (GRID_COLUMNS)
            int col = i % GRID_COLUMNS;

            // 5. Add the TowerView to the GridPane
            gridView.add(towerGardItemView.getContent(), col, row);
        }
    }

    private void pauseGameServices() {
        gameStateManager.suspend();
    }

    private void resumeGameServices() {
        gameStateManager.continueProcessing();
    }

    @FXML
    private void handleGoMarket() {
        handleSceneTransition("Market");
    }

    @FXML
    private void handleGoStore() {
        handleSceneTransition("Store");
    }

    @FXML
    private void handleSceneTransition(String sceneName) {
        pauseGameServices();
        SceneUtil.getInstance().switchToScene(sceneName, result -> {
            resumeGameServices();
            resetAndRefreshGridView();
        });
    }

    @FXML
    private void handleClickExit() {
        Platform.exit();
        System.exit(0);
    }

    private void dispose() {
        gameStateManager.cleanup(this);
    }

    private void handleGameSuccess() {
        if (isSuccess.getAndSet(true)) {
            return;
        }
        Platform.runLater(this::processGameSuccessOnUIThread);
    }

    private void processGameSuccessOnUIThread() {
        showSuccessAlert();
        onAlertConfirmed();
        dispose();
    }

    private void showSuccessAlert() {
        ToastUtil.showAlert("Congratulations! You've triumphed in Level " + GameEnvironment.getInstance().getGameRound() + "!\nEmbark on more thrilling adventures ahead!", "Victory!");
    }

    private void onAlertConfirmed() {
        towerManagementService.reset();
        GameEnvironment.getInstance().rewardPlayerOnRoundEnd();
        navigateToNextState();
    }

    private void navigateToNextState() {
        SceneUtil.getInstance().closeCurrent();
        if (GameEnvironment.getInstance().hasNextRound()) {
            SceneUtil.getInstance().switchToGamePlay();
            GameEnvironment.getInstance().roundUp();
        } else {
            String rewardsInfo = String.format("Rewards: +%s Coins", GameEnvironment.getInstance().getCoin().toPlainString());
            ToastUtil.showAlert("Victory!\n" + rewardsInfo, "Tip");
        }
    }

    private void resetAndRefreshGridView() {
        gridView.getChildren().clear();
        refreshTowerView();
    }

    @Override
    public void onGameFail() {
        Platform.runLater(() -> {
            synchronized (GamePlayController.this) {
                dispose();
                ToastUtil.showAlert("Game Over", "Tip", () -> {
                });
            }
        });
    }

    @Override
    public void onGameWin() {
        handleGameFinish(true);
    }

    private void handleGameFinish(boolean isWin) {
        // 根据游戏结果展示不同UI反馈
        if (isWin) {
            handleGameSuccess();
        } else {
            dispose();
            ToastUtil.showAlert("Game Over", "Tip", () -> {
                // 失败时的UI反馈处理
            });
        }
    }
}
